using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Windows.Forms;
using System.Xml.Serialization;
using Rolodex.Model;
using Rolodex.Properties;
using Rolodex.Views;
using System.ComponentModel;

namespace Rolodex.ApplicationControllers
{
    public partial class Controller
    {
        #region Members
        private MainView _MainView;
        private CardCollection _CardCollection = new CardCollection();
        private List<Card> _SearchResults = new List<Card>();
        private int _CurrentSearchResultIndex;
        #endregion

        #region Properties
        private CardCollection CardCollection
        {
            get
            {
                if (null == this._CardCollection)
                {
                    this._CardCollection = new CardCollection();
                }
                return this._CardCollection;
            }
            set { this._CardCollection = value; }
        }
        #endregion

        #region Methods
        public void MainView_Show()
        {
            this._MainView = new MainView();

            this._MainView.buttonNew.Click +=
                new EventHandler(MainView_buttonNew_Click);
            this._MainView.buttonEdit.Click += 
                new EventHandler(MainView_buttonEdit_Click);
            this._MainView.buttonDelete.Click +=
                new EventHandler(MainView_buttonDelete_Click);
            this._MainView.linklabelEmailAddress.DoubleClick += 
                new EventHandler(MainView_linklabelEmailAddress_DoubleClick);
            this._MainView.textboxCriteria.TextChanged += 
                new EventHandler(MainView_textboxCriteria_TextChanged);
            this._MainView.buttonSearch.Click += 
                new EventHandler(MainView_buttonSearch_Click);
            this._MainView.buttonClear.Click += 
                new EventHandler(MainView_buttonClear_Click);
            this._MainView.comboboxLetter.SelectedIndexChanged += 
                new EventHandler(MainView_comboboxLetter_SelectedIndexChanged);
            this._MainView.buttonPrevious.Click +=
                new EventHandler(MainView_buttonPrevious_Click);
            this._MainView.buttonNext.Click +=
                new EventHandler(MainView_buttonNext_Click);
            this._MainView.menuitemLink.Click += 
                new EventHandler(MainView_menuitemLink_Click);
            this._MainView.menuitemOpen.Click +=
                new EventHandler(MainView_menuitemOpen_Click);
            this._MainView.menuitemRefresh.Click +=
                new EventHandler(MainView_menuitemRefresh_Click);
            this._MainView.menuitemSave.Click += 
                new EventHandler(MainView_menuitemSave_Click);
            this._MainView.menuitemExit.Click += 
                new EventHandler(MainView_menuitemExit_Click);
            this._MainView.Cards.PositionChanged +=
                new EventHandler(MainView_Cards_PositionChanged);
            this._MainView.timerRefresh.Tick += 
                new EventHandler(MainView_timerRefresh_Tick);
            this._MainView.NotifyIcon.DoubleClick += 
                new EventHandler(MainView_NotifyIcon_DoubleClick);
            this._MainView.KeyUp += 
                new KeyEventHandler(MainView_KeyUp);
            this._MainView.Resize +=
                new EventHandler(MainView_Resize);
            this._MainView.FormClosing += 
                new FormClosingEventHandler(MainView_FormClosing);

            this.Initialise();

            this._AppContext.MainForm = this._MainView;

            this._MainView.Show();

            this._MainView.comboboxLetter.SelectedIndex = 0;
        }

        #region Event Handlers
        private void MainView_KeyUp(object sender, KeyEventArgs e)
        {
            MainView theParentView =
                sender as MainView;

            switch (e.KeyCode)
            {
                case Keys.Left:
                    this.MainView_buttonPrevious_Click(
                        theParentView.buttonPrevious, new EventArgs());
                    break;
                case Keys.Right:
                    this.MainView_buttonNext_Click(
                        theParentView.buttonNext, new EventArgs());
                    break;
                case Keys.O:
                    if (e.Control)
                    {
                        this.MainView_menuitemOpen_Click(
                            theParentView.menuitemOpen, new EventArgs());

                    }
                    break;
                case Keys.R:
                    if (e.Control)
                    {
                        this.MainView_menuitemRefresh_Click(
                            theParentView.menuitemOpen, new EventArgs());

                    }
                    break;
                case Keys.S:
                    if (e.Control)
                    {
                        this.MainView_menuitemSave_Click(
                            theParentView.menuitemOpen, new EventArgs());

                    }
                    break;
            }
            e.Handled = true;
        }

        private void MainView_textboxCriteria_TextChanged(object sender, EventArgs e)
        {
            TextBox theCriteriaTextBox =
                sender as TextBox;

            this._MainView.buttonSearch.Enabled =
                !String.IsNullOrEmpty(theCriteriaTextBox.Text) &&
                !theCriteriaTextBox.Text.Equals("Type here to search...");
        }

        private void MainView_comboboxLetter_SelectedIndexChanged(object sender, EventArgs e)
        {
            ComboBox theLetterComboBox =
                sender as ComboBox;

            foreach (Card thisCard in this._MainView.Cards)
            {
                if (thisCard.Letter.ToString().Equals(theLetterComboBox.SelectedItem) ||
                    (theLetterComboBox.SelectedItem.Equals("#") &&
                    Char.IsNumber(thisCard.Letter)))
                {
                    this._MainView.Cards.Position =
                        this._MainView.Cards.IndexOf(thisCard);
                    break;
                }
            }
        }

        private void MainView_timerRefresh_Tick(object sender, EventArgs e)
        {
            this.Initialise();
        }

        private void MainView_NotifyIcon_DoubleClick(object sender, EventArgs e)
        {
            this._MainView.Show();
            this._MainView.WindowState = FormWindowState.Normal;
        }

        private void MainView_Resize(object sender, EventArgs e)
        {
            if (this._MainView.WindowState.Equals(
                FormWindowState.Minimized))
            {
                this._MainView.Hide();
            }
        }
        
        private void MainView_Cards_PositionChanged(object sender, EventArgs e)
        {
            this.ResetNumbering();
        }
        
        private void MainView_buttonPrevious_Click(object sender, EventArgs e)
        {
            if (!String.IsNullOrEmpty(this._MainView.textboxCriteria.Text) &&
                !this._SearchResults.Count.Equals(0))
            {
                if (this._CurrentSearchResultIndex.Equals(0))
                {
                    this._CurrentSearchResultIndex = this._SearchResults.Count - 1;
                }
                else
                {
                    this._CurrentSearchResultIndex--;
                }

                this.DisplaySelectedCard(
                    this._SearchResults[this._CurrentSearchResultIndex]);

                this._MainView.labelSearchResultPosition.Text =
                    String.Format(CultureInfo.CurrentCulture,
                        "Search Results {0} of {1}",
                        this._CurrentSearchResultIndex + 1,
                        this._SearchResults.Count);
            }
            else
            {
                if (this._MainView.Cards.Position.Equals(0))
                {
                    this._MainView.Cards.MoveLast();
                }
                else
                {
                    this._MainView.Cards.MovePrevious();
                }
            }
        }

        private void MainView_buttonNext_Click(object sender, EventArgs e)
        {
            if (!String.IsNullOrEmpty(this._MainView.textboxCriteria.Text) &&
                !this._SearchResults.Count.Equals(0))
            {
                if (this._CurrentSearchResultIndex.Equals(this._SearchResults.Count - 1))
                {
                    this._CurrentSearchResultIndex = 0;
                }
                else
                {
                    this._CurrentSearchResultIndex++;
                }

                this.DisplaySelectedCard(
                    this._SearchResults[this._CurrentSearchResultIndex]);

                this._MainView.labelSearchResultPosition.Text =
                    String.Format(CultureInfo.CurrentCulture,
                        "Search Results {0} of {1}",
                        this._CurrentSearchResultIndex + 1,
                        this._SearchResults.Count);
            }
            else
            {
                if (this._MainView.Cards.Position.Equals(
                    this._MainView.Cards.Count - 1))
                {
                    this._MainView.Cards.MoveFirst();
                }
                else
                {
                    this._MainView.Cards.MoveNext();
                }
            }
        }
        
        private void MainView_menuitemLink_Click(object sender, EventArgs e)
        {
            try
            {
                Process.Start("http://www.ne0ge0.com");
            }
            catch (Win32Exception) { }
        }

        private void MainView_menuitemSave_Click(object sender, EventArgs e)
        {
            this.WriteCardCollection();
            this.Initialise();
        }

        private void MainView_menuitemRefresh_Click(object sender, EventArgs e)
        {
            this.Initialise();
        }
        
        private void MainView_menuitemOpen_Click(object sender, EventArgs e)
        {
            this._MainView.OpenFileDialog.Title = 
                this._MainView.Text;
            this._MainView.OpenFileDialog.InitialDirectory =
                RegistryAgent.CardCollectionFile.DirectoryName;

            switch (this._MainView.OpenFileDialog.ShowDialog(this._MainView))
            {
                case DialogResult.OK:
                    RegistryAgent.CardCollectionFile =
                        new FileInfo(this._MainView.OpenFileDialog.FileName);

                    this.Initialise();
                    break;
            }
        }

        private void MainView_menuitemExit_Click(object sender, EventArgs e)
        {
            this._MainView.FormClosing -=
                new FormClosingEventHandler(MainView_FormClosing);

            this._MainView.Close();
        }

        private void MainView_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (e.CloseReason != CloseReason.WindowsShutDown)
            {
                e.Cancel = true;
                this._MainView.WindowState = FormWindowState.Minimized;

                return;
            }
            this.WriteCardCollection();
        }

        private void MainView_linklabelEmailAddress_DoubleClick(object sender, EventArgs e)
        {
            Card theCurrentCard = 
                this._MainView.Cards.Current as Card;

            Process.Start(String.Format(
                CultureInfo.CurrentCulture,
                "mailto:{0}",
                theCurrentCard.EmailAddress));
        }

        private void MainView_buttonSearch_Click(object sender, EventArgs e)
        {
            this._SearchResults =
                this.SearchCards(this._MainView.textboxCriteria.Text);

            if (this._SearchResults.Count > 0)
            {
                this._CurrentSearchResultIndex = 0;
                
                this.DisplaySelectedCard(
                    this._SearchResults[this._CurrentSearchResultIndex]);

                this._MainView.labelSearchResultPosition.Text =
                    String.Format(CultureInfo.CurrentCulture,
                        "Search Results {0} of {1}",
                        this._CurrentSearchResultIndex + 1,
                        this._SearchResults.Count);
            }

            this._MainView.buttonClear.Enabled =
                this._MainView.labelSearchResultPosition.Visible =
                    !this._SearchResults.Count.Equals(0);
        }

        private void MainView_buttonClear_Click(object sender, EventArgs e)
        {
            this._SearchResults.Clear();
            this._CurrentSearchResultIndex = 0;

            this._MainView.textboxCriteria.Text = "Type here to search...";
            this._MainView.buttonClear.Enabled = false;
            this._MainView.labelSearchResultPosition.Visible = false;
            this._MainView.buttonPrevious.Enabled = true;
            this._MainView.buttonNext.Enabled = true;

            this._MainView.Cards.MoveFirst();

            this._MainView.EnableView();
        }

        private void MainView_buttonNew_Click(object sender, EventArgs e)
        {
            this._MainView.timerRefresh.Stop();

            this.CardAdministrationView_Show(
                CardAdministrationMode.Add,
                new Card());

            this._MainView.timerRefresh.Start();
        }
        
        private void MainView_buttonEdit_Click(object sender, EventArgs e)
        {
            this._MainView.timerRefresh.Stop();

            this.CardAdministrationView_Show(
                CardAdministrationMode.Edit,
                this._MainView.Cards.Current as Card);

            this._MainView.timerRefresh.Start();
        }

        private void MainView_buttonDelete_Click(object sender, EventArgs e)
        {
            Card theCurrentCard =
                this._MainView.Cards.Current as Card;

            if (null != theCurrentCard)
            {
                switch (MessageBox.Show(
                    "Are you sure you want to delete this card?",
                    this._MainView.Text,
                    MessageBoxButtons.YesNo,
                    MessageBoxIcon.Question,
                    MessageBoxDefaultButton.Button2))
                {
                    case DialogResult.Yes:
                        this.CardCollection.CardList.Remove(
                            theCurrentCard);

                        this._MainView.Cards.DataSource =
                            this.CardCollection.CardList;

                        if (this.CardCollection.CardList.Count.Equals(0))
                        {
                            this._MainView.Cards.DataSource =
                                new Card();
                        }
                        else
                        {
                            this._MainView.Cards.MoveFirst();
                        }
                        break;
                    default:
                        break;
                }
            }
        }
        #endregion

        #region Private Helpers
        private void Initialise()
        {
            this._MainView.NotifyIcon.Icon =
                Resources.Refreshing;

            Application.DoEvents();

            int theCurrentPosition =
                this._MainView.Cards.Position;

            this._MainView.labelCardCollectionPath.Text =
                RegistryAgent.CardCollectionFile.FullName;

            this.ReadCardCollection();

            this.SortCardCollection();

            if (this.CardCollection.CardList.Count > 0)
            {
                this._MainView.Cards.DataSource =
                    this.CardCollection.CardList;

                this._MainView.Cards.MoveFirst();

                this._MainView.EnableView();

                this.ResetNumbering();
            }
            else
            {
                this._MainView.DisableView();
            }

            this._MainView.NotifyIcon.Icon =
                Resources.Ready;

            this._MainView.Cards.Position =
                theCurrentPosition;

            this._MainView.comboboxLetter.SelectedIndex = 0;

            Application.DoEvents();
        }

        private void ReadCardCollection()
        {
            if (RegistryAgent.CardCollectionFile.Exists)
            {
                XmlSerializer theSerializer = 
                    new XmlSerializer(typeof(CardCollection));
                TextReader theTextReader =
                    new StreamReader(RegistryAgent.CardCollectionFile.FullName);
                this.CardCollection =
                    theSerializer.Deserialize(theTextReader) as CardCollection;
                theTextReader.Close();
            }
        }

        private void WriteCardCollection()
        {
            if (RegistryAgent.CardCollectionFile.Exists)
            {
                RegistryAgent.CardCollectionFile.Delete();
            }

            XmlSerializer theSerializer =
                new XmlSerializer(typeof(CardCollection));
            TextWriter theTextWriter =
                new StreamWriter(RegistryAgent.CardCollectionFile.FullName);
            theSerializer.Serialize(theTextWriter, this.CardCollection);
            theTextWriter.Close();
        }

        private void SortCardCollection()
        {
            this.CardCollection.CardList.Sort(
                delegate(Card x, Card y)
                {
                    int theLetterComparison =
                        Comparer<char>.Default.Compare(x.Letter, y.Letter);

                    if (theLetterComparison.Equals(0))
                    {
                        return Comparer<string>.Default.Compare(x.Title, y.Title);
                    }
                    return theLetterComparison;
                }
            );
        }

        private List<Card> SearchCards(string theCriteria)
        {
            List<Card> theResults = new List<Card>();

            foreach (Card thisCard in this._CardCollection.CardList)
            {
                if (thisCard.IsMatch(theCriteria))
                {
                    theResults.Add(thisCard);
                }
            }

            return theResults;
        }

        private void DisplaySelectedCard(Card theSelectedCard)
        {
            if (null != theSelectedCard)
            {
                foreach (Card thisCard in this._MainView.Cards)
                {
                    if (thisCard.Equals(theSelectedCard))
                    {
                        this._MainView.Cards.Position =
                            this._MainView.Cards.IndexOf(thisCard);
                    }
                }
            }
        }

        public void ResetNumbering()
        {
            this._MainView.labelRecordPosition.Text =
                String.Format(CultureInfo.CurrentCulture,
                    "Card {0} of {1}",
                    this._MainView.Cards.Position + 1,
                    this._MainView.Cards.Count);
        }
        #endregion
        #endregion
    }
}
